﻿using System;
using System.ComponentModel.Composition;
using Cubicle.Core.Interfaces;

namespace Cubicle.Core.Processors.Transform
{
    [Export("Cubicle.Processors.Transform.DoubleArrayTransformProcessor", typeof(IProcessor<InstructionRequest>))]
    [ExportMetadata("Name", "DoubleArrayTransformProcessor")]
    [ExportMetadata("Description", "Transforms 2D arrays into jagged arrays")]
    public class DoubleArrayTransformProcessor : InstructionRequestProcessor
    {
        #region Overrides of Processor<InstructionRequest>

        public DoubleArrayTransformProcessor() : base(RequestType.Completed) {}

        public override bool Condition(InstructionRequest request)
        {
            if (request.Result() == null) return false;
            var type = request.Result().GetType();
            return base.Condition(request)
                && type.IsArray
                && type.GetArrayRank() == 2;
        }

        public override InstructionRequest ConditionalProcess(InstructionRequest request)
        {
            // Find array type
            var elementType = request.Result().GetType().GetElementType();

            // Find size of first dimension
            var data = (Array)request.Result();
            var dimLength1 = data.GetLength(0);
            var dimLength2 = data.GetLength(1);

            // Construct double array
            var result = Array.CreateInstance(elementType, dimLength1);
            result = Array.CreateInstance(result.GetType(), dimLength1);

            // Initialise double array
            for (var dim1 = 0; dim1 < dimLength1; dim1++)
            {
                var arr = Array.CreateInstance(elementType, dimLength2);
                result.SetValue(arr, dim1);
                for (var dim2 = 0; dim2 < dimLength2; dim2++)
                    arr.SetValue(data.GetValue(dim1, dim2), dim2);
            }

            // Return result
            request.Complete(result);
            return request;
        }

        #endregion
    }
}